<?php
class multitender_action_searchform extends multitender_action {

    public $total=0;
    /**
     * Ссылка на объект search из view.action
     * @var multitender_model_search
     */
    public $s_obj;

    function run() {
        if (empty($this->s_obj)) {
            $this->s_obj = new multitender_model_search();
        }
        $search = $this->s_obj->search;

        $form_data = multitender_model_data_common::singleton();

        $form = array();

        foreach($form_data->get_raw('okrug') as $id => $v) {
            $form['location'][1]['open']             = 1;
            $form['location'][1]['on']               = 1;
            $form['location'][1]['okr'][$id]         = $v;
            $form['location'][1]['okr'][$id]['on']   = isset($search['okr'][$v['id']]) ? 1 : 0;
            $form['location'][1]['okr'][$id]['regs'] = array();
            $form['location'][1]['okr'][$id]['open'] = 0;
        }

        foreach($form_data->get_raw('region') as $id => $v) {
            if ($v['okrug_id']>0) {
                $form['location'][1]['okr'][$v['okrug_id']]['regs'][$id] = array(
                        'id'    => $v['id'],
                        'name'  => $v['name'],
                        'sname' => $v['sname'],
                        'on'    => isset($search['reg'][$id]) ? 1 : 0,
                );
                if (isset($search['reg'][$id])) {
                    $form['location'][1]['okr'][$v['okrug_id']]['open'] = 1;
                } else {
                    $form['location'][1]['on'] = 0;
                }
            } else {
                $cid = Ceil( $id / 100 );
                $form['location'][$cid]['regs'][$id] = array(
                        'id'    => $v['id'],
                        'name'  => $v['name'],
                        'sname' => $v['sname'],
                        'on'    => isset($search['reg'][$id]) ? 1 : 0,
                );             
                if (isset($search['reg'][$id])) {
                    $form['location'][$cid]['open'] = 1;                   
                }
            }
            $regions[$id] = array(
                    'id'    => $v['id'],
                    'name'  => $v['name'],
                    'sname' => $v['sname'],
                    'on'    => isset($search['reg'][$id]) ? 1 : 0,
            );
        }

        if ((empty($search['reg']) && empty($search['okr'])) || (isset($search['reg'][0]))) {
            $form['location'][1]['on'] = 1;
        }

        for ($i=1; $i<=count($form['location']); $i++) {
            $form['location'][$i]['name'] = $form['location'][$i]['regs'][$i*100]['name'];
            $form['location'][$i]['id']   = $i;
            if (isset($search['reg'][$i*100])) { $form['location'][$i]['on'] = 1; $form['location'][$i]['open'] = 0; }
            unset($form['location'][$i]['regs'][$i*100]);
        }


        $types_all  = true;  // если все checked - CHECKED
        $tpl=$this->new_tpl();
        if (empty ($_REQUEST['search']['type'])) {
            $tpl->assign( 'form_type_com' , 'checked="checked"' );
            $comisset = TRUE;
        } else {
            $comisset = FALSE;
        }

        foreach($form_data->get_raw('type') as $id => $v) {
            // вложеные пропускаем
            if((!empty($v['parent_id'])) || ($v['id']==100) || ($v['id']==9)) {
                continue;
            }

            $on = 1;
            if (!empty($search['type'])) {
                if(!isset($search['type'][$id])) {
                    $on = 0;
                    $types_all = false;
                }
            }

            $form['type'][$id]       = $v;
            $form['type'][$id]['on'] = $on;
        }

        $ext = false;
        foreach ($search as $k => $v) {
            if (!empty($v['gozall'])) { continue; }
            if ( !preg_match("#main|myregion#i", $k)) {  $ext = true;  }
        }

        // Избранные запросы
        $user_id = $this->conf['user']['id'];
        if ($user_id) {
            $fqm = $this->new_model("favorite_queries");
            $fqids = $fqm->get_favorities($user_id);
            $lqm = $this->new_model('list_queries');
            $items = $lqm->getList($fqids);
            if ($items) {
                $s_obj = new multitender_model_search();
                foreach( $items as &$v ) {
                    $v['search'] = unserialize($v['search']);
                    $s_obj->SetSearch( $v['search'] );
                    $v['search_txt'] = $s_obj->to_info();
                    $v['search_url'] = $s_obj->to_url();

                    $v['name'] = trim(@$v['search']['main']);
                    if ($v['search_txt']) {
                        $v['name'] .= " ({$v['search_txt']})";
                    }
                    if ( ! $v['name'] ) {
                        $v['name'] = "[ЗАПРОС]";
                    }
                }
                $tpl->assign('items', $items);
            }
        }

        $pagereg = (defined('REGION_CHPU_ID')) ? REGION_CHPU_ID : FALSE;
        if ($pagereg) { $ext = false; }
        $tpl->assign('ext_tab', $ext);

        if ((!empty($search['type'])) && (isset($search['type'][100])) && $comisset !== TRUE) {
            $tpl->assign( 'form_type_com' , 'checked="checked"' );
        }
        if ( $types_all || (!empty($search['type']['gozall']))) {
            $tpl->assign( 'form_types_all', 'checked="checked"' );
        }
        $tpl->assign('form',   $form);
        $tpl->assign('search', $search);
        $tpl->assign('location', $form['location']);
        $tpl->assign('type', $form['type']);
        $tpl->assign('form_info',  $this->s_obj->to_info());
        $search_info = $this->s_obj->to_info_param();
        $tpl->assign('search_info', $search_info);

        $tpl->assign('action', $this->conf['pref']['link_base']);

        // hidden values
        $hidden = array();
        if (!empty($search['customer'])) {
            foreach ($search['customer'] as $key => $value) {
                $hidden["search[customer][$key]"] = 'on';
            }
        }
        if (!empty($search['rubric'])) {
            foreach ($search['rubric'] as $key => $value) {
                $hidden["search[rubric][$key]"] = 'on';
            }
        }

        $tpl->assign('hidden', $hidden);

        $ex_obj  = new multitender_model_example();

        if (empty($search['main'])) {
            $rnd_best = $ex_obj->get_rnd_best();
            $info_text="Например, <a href='/tenders/?search[main]=".rawurlencode($rnd_best)."'>".$rnd_best."</a>";
        } else {
            if ($this->total < 300) {
                $didyoumean   = $this->try_find_error_word($this->s_obj->search['main'],$this->db);
                $didyoumean_b = $this->try_find_error_word($this->s_obj->search['main'],$this->db, "<font color='red'><b><i>WORD</i></b></font>");
                if ($didyoumean !== $this->s_obj->search['main']) {
                    $didyoumean_text = "возможно вы имели в виду <a href='/tenders/?search[main]=" .
                            rawurlencode($didyoumean)."'>".$didyoumean_b."</a>";
                } else {
                    $didyoumean_text = false;
                }
            }
            $info_text = "<u>Подсказка:</u> ";

            if ($this->total == 0 && $this->s_obj->search_error ) {
                $info_text .= "<b>ошибка в запросе</b>, " . $this->s_obj->translate_error($this->s_obj->search_error);
            } elseif ($this->total < 99) {
                if ( isset($this->s_obj->search['main']) && strlen(preg_replace( '/\S+/', '', $this->s_obj->search['main'])) > 5 ) {
                    $info_text .= "возможно вы ввели длинный запрос, сократив количество слов вы получите больше информации.";
                } else {
                    if ($didyoumean_text) {
                        $info_text .= $didyoumean_text;
                    } else {
                        $info_text .= "возможно вы ввели неточный или слишком длинный запрос, попробуйте подобрать другие слова для поиска.";
                    }
                }
            } elseif ($this->total > 1000) {
                $info_text .= "возможно вы захотите органичить поиск вашим регионом - это можно сделать нажав расширенный поиск.";
            } else {
                $info_text = "Подсказка: " . $ex_obj->get_rnd_tips();
            }
        }
        $tpl->assign('info', $info_text);

        $tpl->assign('form_info',  $this->s_obj->to_info());

        if(isset($_GET['newpage'])) {
            $tpl->assign('target',  'target="_blank"' );
        }
        else {
            $tpl->assign('target',  null );
        }

        if( sizeof( @$this->s_obj->search['reg']) === 1 ) {
            $id = (int) array_shift( array_keys($this->s_obj->search['reg']));
            $region = $regions[$id];
            $this->conf['page']['description']  = 'госзаказ ' . $region['name'];
        }

        $this->conf['page_title'] = $this->s_obj->info_main();

        $feed_title = $this->s_obj->info_main();
        if ($feed_title) {
            $feed_title = "$feed_title";
        } else {
            $feed_title = "Все новые тендеры";
        }
        $feed_title = "Мультитендер.ру :: $feed_title";
        $feed_title = trim($feed_title);
        $feed_link = $this->s_obj->to_url();
        $feed_link = $feed_link ? "?$feed_link" : '';
        $this->conf['page_joomla_links'][] = '<link href="' . $this->conf['pref']['link_base_rss'] . $feed_link  . '" ' .
                'rel="alternate" type="application/rss+xml" title="' . $feed_title . '"';

        return $tpl->fetch('searchform.tpl');
    }

    /**
     * Реализация Did You Mean
     * @param string $string
     * @param ADODB  $db
     * @param string $b шаблон, содержащий WORD
     * @return string
     */
    function try_find_error_word($string, &$db, $b=false) {
        require_once $this->conf['libdir'] . '/soundex.php';

        $string = trim(preg_replace(array('#["/_]#', '/\s+/'), ' ', $string));

        // Вес будет считаться как отношение расстояния Левенштейна и частоты слова
        $k_lev   = 0.6;
        $k_cnt   = 0.4;
        $lev_max = 5;   // максимальное расстояние Левенштейна

        // подготовка предложения
        $words = explode(' ', mb_strtolower($string,'UTF-8'));

        $i=-1;
        $res_sent = array(); // строка куда будем записывать результирующие слова из предложения
        // для каждого слова в запросе находим альтернативу
        foreach ($words as $req) {
            $i++;
            $crc = crc_p($req);
            // смотрим, если слово есть в базе и оно в есть в словарке,
            // то проблем с ним нет, пропускаем его
            if ($db->GetCol("SELECT is_dict FROM morf_words WHERE crc=$crc AND is_dict=1")) {
                continue;
            }

            // если слово не в базе или оно не в словаре, то проверяем его

            // находим хеш
            $mktf = (int)dmword($req);

            // TODO сейчас на слово proectov предлагается проект
            // нужно искать не лексемы, а слова

            $rescol = $db->GetCol('SELECT DISTINCT lemma_crc FROM morf_words WHERE soundex='.$mktf);

            // если в базе нет даже приблизительно похожего на это слово, то с ним закончили
            if (empty($rescol)) {
                break;
            }

            // ищем леммы для этого слова
            $res = $db->GetArray('SELECT lemma,cnt,is_dict FROM morf_lemmas WHERE crc in ('.implode(',',$rescol).')');

            // массивы слов из словаря и слов не из словаря соответственно.
            $arr = array();
            $jj  = array();
            foreach ($res as $fld) {
                unset($jj);
                $jj['cnt'] = $fld['cnt'];
                $jj['lemma'] = $fld['lemma'];
                // левенштейн по транслиту и без него, и выбираем минимальное значение
                $leva = min(levenshtein($fld['lemma'],$req),
                        levenshtein(translit_ru($fld['lemma']),translit_ru($req)));
                $jj['lev'] = $leva;
                // проверяем порог для левенштейна
                if ($leva<=$lev_max) {
                    $arr[] = $jj;
                }
            }
            // суммарная популярность слов
            $koef = 0;
            $max  = 0;
            foreach ($arr as $a) {
                $koef += $a['cnt'];
                // максимальное расхождение по Левенштейну
                $max = $max<$a['lev']?$a['lev']:$max;
            }

            $res_arr = Array();
            foreach ($arr as &$a) {
                $ves = $k_lev*(($max-$a['lev'])/$max) + $k_cnt*($a['cnt']/$koef);
                $a['ves'] = $ves;
                $a['ves_cnt'] = ($a['cnt']/$koef);
                $a['ves_lev'] = (($max-$a['lev'])/$max);
                $res_arr[$a['lemma']] = $ves;
            }

            arsort($res_arr);

            $word_sent['org_word'] = $req;
            $word_sent['rep_word'] = array_shift(array_keys($res_arr));
            $word_sent['ves']      = array_shift(array_values($res_arr));
            $word_sent['ind']      = $i;
            $res_sent[]            = $word_sent;
        }

        // завершение обработки предложения
        // меняем ТОЛЬКО одно слово с максимальным весом
        $mx  = -1000;
        $ind = -1;
        foreach ($res_sent as $s) {
            if ($mx<$s['ves']) {
                $mx=$s['ves'];
                $ind = $s['ind'];
                $slovo = $s['rep_word'];
            }
        }
        if ($ind>=0) {
            if ($b) {
                $words[$ind] = str_replace('WORD', $slovo, $b);
            } else {
                $words[$ind] = $slovo;
            }
        }

        return implode(' ',$words);
    }

}

